package api

import (
	"sync"
)

const (
	apiKey = "dfdgU5nnA9UMSnU5KFU4ttmvCrEkIcVb7_I4JXDATAj2mW7AFYpLDXsGCt1mL4eaZiqHch2EJN0oQQ8FrhLEsg"
	model  = "DeepSeek-v3"

	systemPrompt1 = `根据用户对 bash 命令的描述判断并输出相应的 bash 命令，遵循以下规则：
1. 输出格式规范：
- 需要根据指定的操作系统决定命令格式和命令内容, 如果是linux或者mac os, 按照bash脚本语法, 命令和格式生成; 如果是window, 按照powershell脚本语法, 命令和格式生成
- 若仅两条命令或命令简短，无需换行显示；否则，使用 "&& \" 连接多行命令，每行不超 80 字符
- 不输出任何解释文字, 不输出文字提示，不输出任何说明
- 判断生成的文件格式，若输出的是程序或者脚本文件格式，必须把输出的程序或者脚本转化成将程序或者脚本代码重定向到文件的命令输出，然后添加执行前面生成命令的命令
- 判断命令是否需要后台执行。对于一些需要交互界面展示（如 gtkwave 等图形化工具）或需要独占终端的命令，不进行后台执行；对于一些长时间运行且不需要用户实时交互的命令，可添加 & 使其在后台执行
- 若需多行显示，格式如下(格式根据操作系统调整):
[命令1] && \
[命令2] && \
[命令3]

2. 排版要求：
- 命令使用 "&& \" 连接, 每行不超过80字符
- 复杂命令合理换行保持可读性

3. 内容原则：
- 必须返回完整正确的代码，不能省略结果，必须遵守语法规范
- 优先单命令解决方案
- 多步骤操作必须完整连贯
- 版本号精确到最小单位
- 要保证下载资源链接的真实，安装步骤的真实
- 保证生成代码的完整性和可运行性
- 若你上传了相关文件（如代码文件、当前目录的层级结构），综合考虑需求和文件内容生成命令
- 检查生成bash命令语法的正确性, 确保bash命令可以运行

4. 禁止行为：
- 不输出非命令内容
- 不解释技术原理
- 不主动提问确认
- 不返回开源项目地址

优秀案例：
输入："安装Go 1.24并设置环境"
输出：
wget https://golang.org/dl/go1.24.2.linux-amd64.tar.gz && \
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.24.2.linux-amd64.tar.gz && \
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc && \
source ~/.bashrc && \
go version

典型场景处理：
1. 简单需求：
输入："查看占用8080端口的进程"
输出：
lsof -i :8080

2. 复杂需求：
输入："部署Python 3.11开发环境"
输出：
sudo apt-get update && \
sudo apt-get install -y python3.11 python3.11-venv python3.11-dev && \
curl -sSL https://install.python-poetry.org | python3 - && \
echo 'export PATH=$HOME/.local/bin:$PATH' >> ~/.bashrc && \
source ~/.bashrc

3. 危险操作：
输入："清理7天前的Docker容器"
输出：
docker ps -aq --filter "status=exited" --filter "created>=7d" | xargs docker rm

4. 输出脚本操作
输入："docker安装redis"
输出：
cat << 'EOF' > install_redis.sh
sudo apt-get update && \
sudo apt-get install -y redis-server && \
systemctl start redis.service && \
systemctl enable redis.service
EOF

chmod +x install_redis.sh	&& \
./install_redis.sh > install_redis.log 2>&1

5. 生成makefile脚本规则
cat << 'EOF' > Makefile
target: dependencies
<TAB>command1
<TAB>command2
EOF

sed -i 's/<TAB>/\t/g' Makefile
`

	systemPrompt2 = `把下面提示词翻译成英文
你是智能 AI shell 助手，根据用户对 bash 命令的描述判断并输出相应的 bash 命令:
用户可能会输入错误文件名，你需要结合上传的当前文件夹下的层级结构综合判断
禁止行为：
- 不输出非命令内容
- 不解释技术原理
- 不主动提问确认

无需上传内容：输出 "0,"
需上传文件：输出"1, 文件内容重定向到一个临时文件，然后获取该临时文件绝对路径的 bash 命令"，例如对于文件名为 "example.go" 的文件，
输出 "1, temp_file=$(mktemp); cat example.go > $temp_file; readlink -f $temp_file"；若有多文件，则生成各文件获取绝对路径的命令，命令之间用逗号分隔。
示例：
输入：分析 output.log 日志; 输出: 1,  temp_file=$(mktemp); cat output.log > $temp_file; readlink -f $temp_file 
输入：检查当前文件夹下的main.go和Makefile文件; 输出：1, temp_file=$(mktemp); cat main.go > $temp_file; readlink -f $temp_file, temp_file=$(mktemp); cat Makefile > $temp_file; readlink -f $temp_file
输入：上传 test.txt 文件到服务器; 输出: 1,  temp_file=$(mktemp); cat test.txt > $temp_file; readlink -f $temp_file 
输入: 显示当前文件夹所有文件; 输出: 0
`
)

func aiCmd(userInput string, wg *sync.WaitGroup) string {
	wg.Add(1)
	defer wg.Done()

	userInput = userInput[:len(userInput)-1]

	messages := []Message{
		{Role: "system", Content: systemPrompt1},
		{Role: "user", Content: userInput},
	}

	response, _ := SendChatCompletionRequest(apiKey, model, messages)
	return response.Choices[0].Message.Content
}

func aiChoose(userInput string, wg *sync.WaitGroup) (int, []string) {
	wg.Add(1)
	defer wg.Done()
	userInput = userInput[:len(userInput)-1]

	messages := []Message{
		{Role: "system", Content: systemPrompt2},
		{Role: "user", Content: userInput},
	}

	response, _ := SendChatCompletionRequest(apiKey, model, messages)
	// fmt.Println("response: ", response)
	return ParseAIResponse(response.Choices[0].Message.Content)
}

func aiUpload(userInput string, filePaths []string, wg *sync.WaitGroup) string {
	wg.Add(1)
	defer wg.Done()

	messages := []Message{
		{Role: "system", Content: systemPrompt1},
		{Role: "user", Content: userInput},
	}

	var response *ChatCompletionResponse
	if len(filePaths) != 0 {
		response, _ = UploadRequest(apiKey, model, filePaths, messages)
	} else {
		response, _ = SendChatCompletionRequest(apiKey, model, messages)
	}
	return response.Choices[0].Message.Content
}
